package com.my.java8;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.annotation.Repeatable;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.DoubleUnaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class FuncInterface {

	@FunctionalInterface
	public interface BufferedReadProcessor{
		String process(BufferedReader b)throws IOException;
	}
	
	public static String processFile(BufferedReadProcessor p)throws IOException{
		try(BufferedReader br = new BufferedReader(new FileReader("c:/HaxLogs.txt"))){
			return p.process(br);
		}
		
	}
	
	public String processFileInst(BufferedReadProcessor p){
		return "";
	}
	
	public static String processFileStat(BufferedReadProcessor p){
		return "";
	}
	
	static DoubleUnaryOperator curriedConverter(double f, double b){
		return (double x) -> x * f + b;
	}
	
	interface MyList<T> {
		T head();
		MyList<T> tail();
		default boolean isEmpty() {
		return true;
		}
	}
	
	static class LazyList<T> implements MyList<T>{
		final T head;
		final Supplier<MyList<T>> tail;
		
		public LazyList(T head,Supplier<MyList<T>> tail) {
			this.head = head;
			this.tail=tail;
		}
		
		@Override
		public T head() {
			return head;
		}

		@Override
		public MyList<T> tail() {
			return tail.get();
		}
		
		public boolean isEmpty(){
			return false;
		}
		
	}
	
	public static LazyList<Integer> from(int n) {
		return new LazyList<Integer>(n, () -> from(n+1));
	}
	
	static <A,B,C> Function<A,C> compose(Function<B,C> g, Function<A,B> f) {
		return x -> g.apply(f.apply(x));
	}
	
	static <A> Function<A, A> repeat(int n,Function<A, A> f){
		return n==0?x->x:compose(f, repeat(n-1, f));
	}
	
	public static void main(String[] args) throws Exception{
		String oneLine = processFile(br->br.readLine());
		System.out.println(oneLine+"...............");
		
		String twoLines =
				processFile(br -> br.readLine() + br.readLine());
		System.out.println(twoLines);
		
		Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
		
		String[] arr = {"sasf","","32323","adfasdfsd"};
		String result = Arrays.asList(arr).parallelStream().filter(nonEmptyStringPredicate).collect(Collectors.joining("-"));
	
		System.out.println(result);
		int local = 4;
		Consumer<String> consumer = s->System.out.println(s+local);
		consumer.accept("dddd");
		
		Runnable r = ()->System.out.println(local);
		
		Function<String, Integer> func = s->Integer.valueOf(s);
		
		
		Function<BufferedReadProcessor, String> fbs = FuncInterface::processFileStat;
		
		FuncInterface fi = new FuncInterface();
		Function<BufferedReadProcessor, String> fbi = fi::processFileInst;
		
		Function<Integer, String> fis = "ddd"::substring;
		System.out.println(fis.apply(1));
		
		BiPredicate<List<String>, String> contains = List::contains;
		
		
		Function<String, Apple> apple = Apple::new;
		
		Function<String, Integer> strToInt = Integer::parseInt;
		
		DoubleUnaryOperator convertCtoF = curriedConverter(9.0/5, 32);
		DoubleUnaryOperator convertUSDtoGBP = curriedConverter(0.6, 0);
		DoubleUnaryOperator convertKmtoMi = curriedConverter(0.6214, 0);
		
		convertUSDtoGBP.applyAsDouble(23.22);
		
		LazyList<Integer> numbers = from(2);
		int two = numbers.head();
		int three = numbers.tail().head();
		int four = numbers.tail().tail().head();
		System.out.println(two + " " + three + " " + four);
		
		System.out.println(repeat(3, (Integer x) -> 2*x).apply(10));
	
	}

}
